package com.zmn.oms.business.impl.xno;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.openservices.shade.org.apache.commons.lang3.StringUtils;
import com.zmn.account.common.utils.NumberUtil;
import com.zmn.base.common.data.common.dro.area.AreaDRO;
import com.zmn.base.common.data.common.dro.tags.TagsDRO;
import com.zmn.base.common.data.dubbo.interfaces.area.AreaListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.oms.business.interfaces.base.BaseCodeService;
import com.zmn.oms.business.interfaces.xno.OrderTempXnoBindBService;
import com.zmn.oms.business.interfaces.xno.OrderXnoBindService;
import com.zmn.oms.common.annotation.ZsNormalOrderWorkLog;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderLogConsts;
import com.zmn.oms.common.constant.OrderXnoConsts;
import com.zmn.oms.common.dto.OmsOperator;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.MobileUtil;
import com.zmn.oms.model.dto.work.xno.TempXnoBindDTO;
import com.zmn.oms.model.dto.work.xno.TempXnoUnBindDTO;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.xno.OrderXnoBind;
import com.zmn.oms.model.entity.xno.OrderXnoBindQuery;
import com.zmn.oms.model.vo.work.detail.ZsXnoBindVO;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.services.interfaces.xno.OrderXnoService;
import com.zmn.xno.dubbo.interfaces.bind.AxbBindRemoteService;
import com.zmn.xno.dubbo.model.bind.AxbBindDIO;
import com.zmn.xno.dubbo.model.bind.AxbBindDRO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

/**
 * @author ：ligang
 * @date ：2022/01/1 11:01
 * @description：临时小号小号相关操作
 */
@Service
@Slf4j
public class OrderTempXnoBindBServiceImpl implements OrderTempXnoBindBService {
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private OrderXnoBindService orderXnoBindService;
    @Autowired
    private OrderXnoService orderXnoService;
    @Autowired
    private BaseCodeService baseCodeService;

    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private AreaListRemoteService areaListRemoteService;
    @DubboReference(version = com.zmn.xno.common.constant.SystemConstants.DUBBO_CONSTS_INTERFACE_VERSION, check = false)
    private AxbBindRemoteService axbBindRemoteService;

    @Override
    public Boolean queryTempXnoBindStatus(OrderWork orderWork, String telephone, String userTelephone) {
        ZsXnoBindVO zsXnoBindVO = orderXnoBindService.queryXNO(telephone, userTelephone, orderWork);
        return zsXnoBindVO != null && Objects.equals(zsXnoBindVO.getStatus(), OrderConsts.BIND_STATUS_BIND);
    }

    @Override
    @Transactional
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_TEMP_XNO_BIND, beforeProceed = false)
    public void bindTempXno(TempXnoBindDTO tempXnoBindDTO, OrderWork orderWork) throws OmsBaseException {
        log.info("tempXnoBind-绑定临时小号 入参：{}", JSON.toJSONString(tempXnoBindDTO));
        // 订单详情
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(tempXnoBindDTO.getWorkId());
        tempXnoBindDTO.setUserTelephone(orderDetail.getTelephone());
        // 判断电话是否是座机
        String code = "";
        ResponseDTO<AreaDRO> byId = areaListRemoteService.getById(orderWork.getCityId());
        if (byId.isSuccess() && byId.getData() != null) {
            code = byId.getData().getAreaNum();
        }
        // 有效时间
        TagsDRO effectiveTimeCodeMap = baseCodeService.getOneBaseCodeMap(com.zmn.consts.GlobalConsts.PLAT_MARK_ZMN, 1105, null);
        // 过期时间
        AxbBindDRO axbBindDRO = this.axbBind(orderDetail, orderWork, tempXnoBindDTO.getBindTelephone(), code, tempXnoBindDTO.getUserTelephone(), Long.valueOf(effectiveTimeCodeMap.getTwoTypeId()) * 60);
        String xno = axbBindDRO.getXno();
        // 设置绑定状态为已绑定
        if (StringUtils.isBlank(xno)) {
            log.info("tempXnoBind-绑定临时小号结果为空：workId={}", tempXnoBindDTO.getWorkId());
            throw new OmsBaseException("临时小号绑定失败");
        }
        // 日志填充
        tempXnoBindDTO.setXnoTelephone(xno);
        // 保存绑定关系
        OrderXnoBind orderXnoBind = OrderXnoBind.builder()
                .orderId(tempXnoBindDTO.getOrderId())
                .workId(tempXnoBindDTO.getWorkId())
                .xnoBindId(axbBindDRO.getBindId())
                .bindTelephone(tempXnoBindDTO.getBindTelephone())
                .bindStatus(OrderConsts.BIND_STATUS_BIND)
                .xnoTelephone(xno)
                .bindType(OrderXnoConsts.BIND_TYPE_TEMP)
                .creater(tempXnoBindDTO.getOperator())
                .updater(tempXnoBindDTO.getOperator())
                .build();
        orderXnoService.saveXnoBind(orderXnoBind);
    }

    @Override
    public boolean isTempXno(Long workId, Long bindId) {
        log.info("临时小号判断入参：workId={} xnoBindId={}", workId, bindId);
        if (Objects.isNull(bindId)) {
            return false;
        }
        OrderXnoBindQuery orderXnoBindQuery = OrderXnoBindQuery.builder()
                .workId(workId)
                .bindType(OrderXnoConsts.BIND_TYPE_TEMP)
                .xnoBindId(bindId)
                .build();
        Integer count = orderXnoService.countXnoBindByQuery(orderXnoBindQuery);
        return count > 0;
    }

    @Override
    public boolean isTempXno(Long workId, String xno, String callerNo, String calledNo) {
        if (Objects.isNull(xno) || Objects.isNull(callerNo) || Objects.isNull(calledNo)) {
            return false;
        }
        OrderXnoBindQuery orderXnoBindQuery = OrderXnoBindQuery.builder()
                .workId(workId)
                .bindType(OrderXnoConsts.BIND_TYPE_TEMP)
                .build();
        List<OrderXnoBind> orderXnoBindList = orderXnoService.queryOrderXnoBindListByQuery(orderXnoBindQuery);
        if (CollectionUtil.isNullOrEmpty(orderXnoBindList)) {
            return false;
        }
        // 主叫或被叫满足一个是操作员电话
        boolean match = orderXnoBindList.stream().anyMatch(orderXnoBind ->
                xno.endsWith(orderXnoBind.getXnoTelephone()) &&
                        (callerNo.endsWith(orderXnoBind.getBindTelephone()) || calledNo.endsWith(orderXnoBind.getBindTelephone()))
        );
        return match;
    }

    @Override
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_TEMP_XNO_UNBIND, beforeProceed = false)
    @Transactional
    public void unTempXnoBind(TempXnoUnBindDTO tempXnoUnBindDTO) throws OmsBaseException {
        log.info("临时小号解绑入参：{}", JSON.toJSONString(tempXnoUnBindDTO));
        // 更新绑定状态
        OrderXnoBind orderXnoBind = OrderXnoBind.builder()
                .workId(tempXnoUnBindDTO.getWorkId())
                .xnoBindId(tempXnoUnBindDTO.getXnoBindId())
                .bindStatus(OrderConsts.BIND_STATUS_UNBIND)
                .updater(GlobalConsts.getOperatorTypeName(GlobalConsts.OPERATE_USER_TYPE_SYSTEM))
                .build();
        orderXnoService.updateOrderXnoBind(orderXnoBind);

        // 日志数据
        OrderXnoBindQuery orderXnoBindQuery = OrderXnoBindQuery.builder()
                .workId(tempXnoUnBindDTO.getWorkId())
                .xnoBindId(tempXnoUnBindDTO.getXnoBindId())
                .bindType(OrderXnoConsts.BIND_TYPE_TEMP)
                .build();
        orderXnoBind = orderXnoService.queryOrderXnoBindByQuery(orderXnoBindQuery);
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(tempXnoUnBindDTO.getOrderId());
        tempXnoUnBindDTO.setBindOperator(orderXnoBind.getCreater());
        tempXnoUnBindDTO.setUserTelephone(orderDetail.getTelephone());
        tempXnoUnBindDTO.setBindTelephone(orderXnoBind.getBindTelephone());
    }

    /**
     * 临时小号联系用户
     *
     * @param omsOperator
     * @param xnoBindId
     */
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_TEMP_XNO_CONTACT_USER, beforeProceed = false)
    public void contactUser(OmsOperator omsOperator, Long xnoBindId) {
        log.info("临时小号联系用户入参：omsOperator={} xnoBindId={}", JSON.toJSONString(omsOperator), xnoBindId);
        OrderXnoBindQuery orderXnoBindQuery = OrderXnoBindQuery.builder()
                .workId(omsOperator.getWorkId())
                .xnoBindId(xnoBindId)
                .bindType(OrderXnoConsts.BIND_TYPE_TEMP)
                .build();
        OrderXnoBind orderXnoBind = orderXnoService.queryOrderXnoBindByQuery(orderXnoBindQuery);
        omsOperator.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_STAFF);
        omsOperator.setOperator(orderXnoBind.getCreater());
    }

    /**
     * 小号绑定
     *
     *
     * @param orderDetail
     * @param orderWork
     * @param bindTelephone
     * @param code
     * @param userTelephone
     * @param expiredDuration
     * @return
     * @throws OmsBaseException
     */
    private AxbBindDRO axbBind(OrderDetail orderDetail, OrderWork orderWork, String bindTelephone, String code, String userTelephone, Long expiredDuration) throws OmsBaseException {
        if (NumberUtil.isNullOrZero(orderDetail.getGridManageCompanyId()) && NumberUtil.isNullOrZero(orderWork.getManageCompanyId())) {
            throw new OmsBaseException("工单不存子公司，不可操作！");
        }
        userTelephone = MobileUtil.isFixedPhone(userTelephone) ? code + userTelephone : userTelephone;
        // 查询绑定关系，如果已绑定，不进行绑定
        ZsXnoBindVO zsXnoBindVO = orderXnoBindService.queryXNO(bindTelephone, userTelephone, orderWork);
        if (zsXnoBindVO != null && Objects.equals(zsXnoBindVO.getStatus(), OrderConsts.BIND_STATUS_BIND)) {
            throw new OmsBaseException(String.format("操作员电话：%s 已存在绑定", bindTelephone));
        }

        Integer spId = orderWork.getManageCompanyId();
        if (NumberUtil.isNullOrZero(spId)) {
            spId = orderDetail.getGridManageCompanyId();
        }

        AxbBindDIO axb = AxbBindDIO.builder()
                .ano(bindTelephone)
                .appKey("oms")
                .atype(3)
                .bizId(orderWork.getWorkId().toString())
                .bno(userTelephone)
                .btype(2)
                .plat(orderWork.getPlatWork())
                .cityId(orderWork.getCityId())
                .level1Id(orderWork.getPlatWork())
                .level2Id(spId)
                .level3Id(orderWork.getCityId())
                .engineerId(orderWork.getMasterId())
                .engineerName(orderWork.getMasterName())
                .expiredDuration(expiredDuration)
                .build();
        log.info("tempXnoBind-小号绑定接口入参：{}", axb);
        ResponseDTO<AxbBindDRO> bindRes = axbBindRemoteService.bindX(axb);
        log.info("tempXnoBind-小号绑定接口出参：orderId :{},{}", axb.getBizId(), JSONObject.toJSONString(bindRes));
        if (bindRes.isSuccess() && bindRes.getData() != null) {
            return bindRes.getData();
        }
        throw new OmsBaseException(bindRes.getStatus(), bindRes.getMessage());
    }
}
